from django.db import DatabaseError
from django.http import JsonResponse
from django.shortcuts import render,redirect
from django.views import View
from django import http
from django.urls import reverse
from django.contrib.auth.__init__ import login,authenticate
import re
from django_redis import get_redis_connection

from users.models import User
from meiduo_mall.utils.response_code import RETCODE,err_msg


# Create your views here.


class RegisterView(View):
    """用户注册"""

    def get(self, request):
        """提供用户注册页面"""
        return render(request, 'register.html')

    def post(self, request):
        """实现用户注册业务逻辑"""

        # 接收参数：表单数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        mobile = request.POST.get('mobile')
        sms_code_client = request.POST.get('sms_code')
        allow = request.POST.get('allow')

        # 校验参数：前后端的校验需要分开，避免恶意用户越过前端逻辑发请求，要保证后端的安全，前后端的校验逻辑相同
        # 判断参数是否齐全
        # all(列表)：会去校验列表中的元素是否为空，只要有一个为空，返回false
        if not all([username, password, password2, mobile, allow]):
            # "如果缺少比传参数，响应错误提示信息，403"
            return http.HttpResponseForbidden("缺少比传参数")
            return JsonResponse({})

        # 判断用户名是否是5-20个字符
        if not re.match(r"[a-zA-Z0-9]{5,20}", username):
            return http.HttpResponseForbidden("请输入5-20个字符的用户名")
        # 判断用户名是否重复
        if User.objects.filter(username=username).exists():
            return http.HttpResponseForbidden("用户名已存在")
        # 判断密码是否是8-20个字符
        if not re.match(r"[a-zA-Z0-9]{8,20}", password):
            return http.HttpResponseForbidden("请输入8-20个由数字和字母组成的密码")
        # 判断两次输入的密码是否一致
        if password != password2:
            return http.HttpResponseForbidden("两次输入密码不一致")
        # 判断手机号是否合法
        if not re.match(r"^1[3-9]\d{9}$", mobile):
            return http.HttpResponseForbidden("手机号码格式不正确")
        # 判断短信验证码是否输入正确
        redis_conn = get_redis_connection("verify_code")
        sms_code_server = redis_conn.get("sms_%s" % mobile)
        if sms_code_server is None:
            return render(request, 'register.html',{"sms_code_errmsg":"短信验证码已失效"})
        if not sms_code_client == sms_code_server.decode():
            return render(request, 'register.html',{"sms_code_errmsg":"输入短信验证码有误！"})

        # 判断用户是否勾选了协议
        if allow != "on":
            return http.HttpResponseForbidden("请勾选用户协议")

        # 保存注册数据：是注册业务的核心
        # User(username=username, mobile=mobile).save()
        # return render(request, 'register.html', {'register_message': "注册失败"})
        try:
            user = User.objects.create_user(username=username, password=password, mobile=mobile)
        except DatabaseError as e:
            # "告诉用户注册失败"
            render(request, 'register.html', {'register_message': "注册失败"})

        # 实现状态保持
        login(request, user)

        # 响应结果：重定向到首页
        # return http.HttpResponse("注册成功，重定向到首页")
        # return redirect("/")
        # return redirect("contents:index")
        # reverse("contents:index")=="/"
        return redirect(reverse("contents:index"))


class UsernameCountView(View):
    """判断用户名是否重复注册"""
    def get(self, request,username):
        """

        :param request:
        :param username: 用户名
        :return:JSON
        """
        # 实现主体业务逻辑：使用username查询对应的记录的条数（filter返回的是满足条件的结果集）
        count = User.objects.filter(username=username).count()
        data = {"code":RETCODE.OK , "errmsg": err_msg.get(RETCODE.OK), "count": count}
        # 响应结果
        return http.JsonResponse(data)


class LoginView(View):
    """
        用户登录
    """
    def get(self, request):
        """提供用户登录页面"""

        return render(request, 'login.html')


    def post(self, request):
        """实现用户登录逻辑"""
        # 接收参数
        username = request.POST.get("username")
        password = request.POST.get("password")
        remembered = request.POST.get("remembered")

        # 校验参数
        if not all([username, password]):
            return http.HttpResponseForbidden("缺少必填参数")
        if not re.match(r"[a-zA-Z0-9]{5,20}",username):
            return http.HttpResponseForbidden("手机号格式错误")
        if not re.match(r"[a-zA-Z0-9]{8,20}",password):
            return http.HttpResponseForbidden("请输入8-20个字符的密码")

        # 业务逻辑
        # 认证用户：使用账号查询用户是否存在，如果用户存在，再校验密码是否正确
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request,"login.html",{"account_errmsg":"账号或密码错误"})
        # 状态保持
        login(request,user)
        # 使用remembered确定状态保持周期（实现记录登录）
        if remembered != "on":
            # 没有记住登录：状态保持在浏览器会话结束后就销毁
            request.session.set_expiry(0) # 单位是秒
        else:
            # 记住登录：状态保持周期为二周：默认是二周
            request.session.set_expiry(None)

        # 响应结果：重定向到首页
        return redirect(reverse("contents:index"))



